import os
import xmltodict
import zipfile

from file_paser.ofd_paser.ofd_utils import get_content_and_line
from file_paser.ofd_paser.ofd_utils import (
    process_content,
    get_limit,
    get_span,
    group_data,
    get_table_data,
    get_other_data,
    format_data,
    get_custom,
)


class Invoice:

    def __init__(self, filestream_or_path):
        self.filestream_or_path = filestream_or_path
        self.result_list = self.parse()

    def get_tree(self, filename):
        """
        :param filename:
        :return:
        """

        if isinstance(self.filestream_or_path, str):
            # "./Doc_0/DocumentRes.xml"
            file_path = os.path.join(self.filestream_or_path, filename)
            with open(file_path, "r", encoding="utf-8") as f:
                _text = f.read()
                tree = xmltodict.parse(_text)
        else:
            # "Doc_0/DocumentRes.xml"
            filename = str(os.path.normpath(filename).replace("\\", "/"))
            with zipfile.ZipFile(self.filestream_or_path) as filestream:
                with filestream.open(filename) as f:
                    tree = xmltodict.parse(f)

        return tree

    def get_page(self):
        """
        获取并整合所有文件的信息
        :return:
        """

        ofd_tree = self.get_tree("OFD.xml")
        doc_path = ofd_tree["ofd:OFD"]["ofd:DocBody"]["ofd:DocRoot"]

        custom_dict = get_custom(ofd_tree)
        doc_root = os.path.split(doc_path)[0]
        doc_tree = self.get_tree(doc_path)

        page_locs = doc_tree["ofd:Document"]["ofd:Pages"]["ofd:Page"]
        if isinstance(page_locs, dict):
            page_locs = [page_locs]

        contents, lines = [], []
        for page_loc in page_locs:
            page_path = page_loc["@BaseLoc"]
            page_tree = self.get_tree(f"{doc_root}/{page_path}")
            if "ofd:Template" in page_tree["ofd:Page"].keys():
                template_path = None
                template_id = page_tree["ofd:Page"]["ofd:Template"]["@TemplateID"]
                template_locs = doc_tree["ofd:Document"]["ofd:CommonData"][
                    "ofd:TemplatePage"
                ]
                if isinstance(template_locs, dict):
                    template_locs = [template_locs]
                for template_loc in template_locs:
                    if template_loc["@ID"] == template_id:
                        template_path = template_loc["@BaseLoc"]
                        break
                template_tree = self.get_tree(f"{doc_root}/{template_path}")
                _, line = get_content_and_line(template_tree, is_template=True)
                content, _ = get_content_and_line(page_tree)
            else:
                content, line = get_content_and_line(page_tree)

            content = process_content(content)
            x_line, y_line = get_limit(line)
            contents.append(content)
            lines.append([x_line, y_line])

        page_nums = len(page_locs)

        return custom_dict, contents, lines, page_nums

    def parse(self):
        """
        ofd发票文档解析全流程
        :param ofd_path: ofd文件目录
        :return: 该ofd文件解析出的结果
        """

        custom_dict, contents, lines, page_nums = self.get_page()

        content = contents[-1]
        x_line, y_line = lines[-1]

        # 2. 根据特殊字符，获取行项目每一行的y坐标
        idx = -4
        span_y, span_x = get_span(content, y_line, idx)

        # 3. 将content中的内容按照y值进行分组，确定每一行的项目
        data_dict = group_data(content, span_y, y_line)

        # 4. 根据path和y对文本进行解析
        other_list = get_other_data(data_dict, x_line, y_line)
        table_list, last_page = get_table_data(data_dict, span_y, y_line, idx)

        # 4.1. 如果有多页，需要对每一页的表格内容进行解析
        if page_nums > 1:
            page_table = []
            idx = -2
            for i in range(page_nums - 1):
                content = contents[i]
                x_line, y_line = lines[i]
                span_y, span_x = get_span(content, y_line, idx)
                data_dict = group_data(content, span_y, y_line)
                table, last_page = get_table_data(
                    data_dict, span_y, y_line, idx, last_page
                )
                page_table.extend(table)

            table_list = page_table + table_list

        # 5.格式化文本
        return format_data(other_list, table_list, custom_dict)
